﻿using DoNet.Common.Cache;
using DoNet.System.Models;

namespace DoNet.Token
{
    /// <summary>
    /// Token数据
    /// 可以改成数据库操作
    /// </summary>
    public class TokenService
    {
        /// <summary>
        /// 缓存Key
        /// </summary>
        private static string keyName = "TokenList";
        /// <summary>
        /// Token缓存列表
        /// </summary>
        private static ListCacheManager<string, Token> _cache = new ListCacheManager<string, Token>();

        /// <summary>
        /// 实现数据库存储逻辑
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="accessToken"></param>
        /// <param name="refreshToken"></param>
        public static bool StoreToken(string appId, string accessToken, int accessExpire, string refreshToken, int refreshExpire)
        {
            try
            {
                long Id = 0;

                var list = _cache.GetListCopy(keyName);
                if (list.Count > 0)
                {
                    Id = list.Max(x => x.Id);
                }

                var now = DateTime.UtcNow;
                DateTime accessExpiresDate = now.AddMinutes(accessExpire);
                DateTime refreshExpiresDate = now.AddDays(refreshExpire);

                var model = new SysAccessToken()
                {
                    Id = Id + 1,
                    AppId = appId,
                    AccessToken = accessToken,
                    AccessExpires = accessExpire,
                    AccessExpiresDate = accessExpiresDate,
                    RefreshToken = refreshToken,
                    RefreshExpires = refreshExpire,
                    RefreshExpiresDate = refreshExpiresDate,
                    IsRevoked = false,
                    CreatedDate = now,
                    ModifiedDate = now
                };

                //实现数据库
                _cache.AppendToList(keyName, model);
                return true;
            }
            catch
            {

            }
            return false;
        }

        /// <summary>
        /// 通过AppId 获取 Token
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        public static SysAccessToken? GetTokenByAppId(string appId)
        {
            //实现数据库
            var list = _cache.GetListCopy(keyName);
            if (list.Count > 0)
            {
                var model = list.Where(x => x.AppId == appId && !x.IsRevoked && x.AccessExpiresDate > DateTime.UtcNow).FirstOrDefault();
                if (model != null)
                    return model;
            }
            return default;
        }

        /// <summary>
        /// 通过RefreshToken 获取 Token
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        public static SysAccessToken? GetTokenByRefreshToken(string refreshToken)
        {
            //实现数据库
            var list = _cache.GetListCopy(keyName);
            if (list.Count > 0)
            {
                return list.Where(x => x.RefreshToken == refreshToken && !x.IsRevoked).FirstOrDefault();
            }
            return default;
        }

        /// <summary>
        /// 通过RefreshToken 更新 Token
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        public static bool UpdateToken(string refreshToken, string newToken, int accessExpire)
        {
            try
            {
                //实现数据库
                var tempList = _cache.GetListCopy(keyName);
                if (tempList.Count > 0)
                {
                    int index = tempList.FindIndex(x => x.RefreshToken == refreshToken && !x.IsRevoked);
                    if (index != -1)
                    {
                        var now = DateTime.UtcNow;
                        tempList[index].AccessToken = newToken;
                        tempList[index].AccessExpires = accessExpire;
                        tempList[index].AccessExpiresDate = now.AddMinutes(accessExpire);
                        tempList[index].ModifiedDate = now;
                    }

                    _cache.RemoveList(keyName);

                    //实现数据库
                    _cache.AddOrUpdateList(keyName, tempList);
                    return true;
                }
            }
            catch
            { }
            return false;
        }

        /// <summary>
        /// 判断token是否已经吊销 (如果token不存在也表示吊销)
        /// (需要判断 AccessToken OR RefreshToken)
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool IsRevoked(string token)
        {
            // 检查吊销列表中是否存在
            var list = _cache.GetListCopy(keyName);
            if (list.Count > 0)
            {
                int index = list.FindIndex(x => (x.AccessToken == token || x.RefreshToken == token) && x.IsRevoked);
                if (index != -1)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 将 appId 所有令牌加入吊销列表
        /// </summary>
        /// <param name="appId"></param>
        public static bool RevokeAllTokens(string appId)
        {
            try
            {
                // 将 appId 所有令牌加入吊销列表
                var tempList = _cache.GetListCopy(keyName);
                if (tempList.Count > 0)
                {
                    var now = DateTime.UtcNow;
                    int index = tempList.FindIndex(x => x.AppId == appId && !x.IsRevoked);
                    if (index != -1)
                    {
                        tempList[index].IsRevoked = true;
                        tempList[index].ModifiedDate = now;
                    }

                    _cache.RemoveList(keyName);

                    //实现数据库
                    _cache.AddOrUpdateList(keyName, tempList);
                    return true;
                }
            }
            catch
            { }
            return false;
        }
    }
}
